package  
{
	import flash.display.NativeMenuItem;
	import flash.display.Shape;
	import flash.filters.BlurFilter;
	import flash.geom.ColorTransform;
	import flash.geom.Matrix;
	import flash.geom.Point;
	import flash.geom.Rectangle;
	import org.flixel.*;
	import levels.Levels;
	/**
	 * ...
	 * @author morgan
	 */
	public class GameState extends FlxState
	{
		
		// FONT EMBEDDING
		//[Embed(source="../data/visitor1.ttf", fontFamily="visitor", embedAsCFF="false")] public var font_visitor:String;
		
		public static var ref:GameState;
		
		public var time:Number = 0;
		
		public var sceneReal:GameScene;
		public var sceneReflection:GameScene;
		
		public var reflectionHeightOffset:Number = 70;
		public var lowestReflectionHeightOffset:Number = 70;
		public var playerScrollOffset:Number = 120;
		
		public var camerasLocked:Boolean = false;
		
		public var realMapStr:String = "0";
		public var reflectMapStr:String = "0";
		
		public function GameState() 
		{
			ref = this;
			
			sceneReal = new GameScene();
			sceneReal.real = true;
			sceneReflection = new GameScene();
			sceneReflection.bgColor = 0xffeef4ff;
			sceneReal.other = sceneReflection;
			sceneReflection.other = sceneReal;
		}
		
		override public function create():void 
		{
			super.create();
			FlxG.bgColor = 0xffff0000;
			
			sceneReal.mapStr = realMapStr;
			sceneReflection.mapStr = reflectMapStr;
			sceneReal.create();
			sceneReflection.create();
		}
		
		/*
		public function makeParticle(x:int, y:int, image:Class, frameSize:int, anim:Array, time:Number, xv:Number, yv:Number, angles:int):void
		{
			var p:Particle = particleGroup.getFirstAvailable() as Particle;
			if (!p)
			{
				p = new Particle();
				particleGroup.add(p);
			}
			p.spawn(x, y, image, frameSize, anim, time, xv, yv, angles);
		}
		*/
		
		override public function update():void 
		{
			super.update();
			if (FlxG.keys.justPressed("ESCAPE"))
			{
				FlxG.switchState(new TitleState());
			}
			
			sceneReal.update();
			sceneReflection.update();

			updateScrolling();
			
			time += FlxG.elapsed;
			
			if (sceneReal.endTrigger.triggered && sceneReflection.endTrigger.triggered)
			{
				FlxG.fade(0xff000000, 1, function():void {
					FlxG.switchState(new Levels.levelOrder[Levels.nextLevel]);
					Levels.nextLevel++;
				});
			}
			
			if (FlxG.keys.justPressed("S"))
			{
				sceneReal.player.saveRec.save();
			}
			if (FlxG.keys.justPressed("L"))
			{
				sceneReflection.player.readRec.load();
				sceneReflection.player.playback = true;
			}
			
		}
		
		public function updateScrolling():void
		{
			if ( Math.abs(sceneReal.player.x - sceneReflection.player.x) < FlxG.width / 2)
			{
				// Scroll based on the average player position if the players are close
				sceneReal.camera.scroll.x = int((sceneReal.player.x + sceneReflection.player.x + sceneReal.player.width) / 2 - FlxG.width / 2);
				sceneReflection.camera.scroll.x = sceneReal.camera.scroll.x;	
				camerasLocked = true;
			}
			else
			{
				// Otherwise scroll independently
				sceneReal.camera.scroll.x = sceneReal.player.x + sceneReal.player.width / 2 - FlxG.width / 2;
				sceneReflection.camera.scroll.x = sceneReflection.player.x + sceneReflection.player.width / 2 - FlxG.width / 2;
				camerasLocked = false;
			}
			if (sceneReal.player.y < playerScrollOffset)
			{
				// Until the 'real' scene is filling the screen (the reflection height offset is half the screen height)
				// scrolling is done by simply adjusting that offset.
				reflectionHeightOffset = int(lowestReflectionHeightOffset - (sceneReal.player.y - playerScrollOffset));
				if (reflectionHeightOffset > FlxG.height / 2)
				{
					// The reflection height offset is too big so now we can start using regular camera scrolling
					reflectionHeightOffset = FlxG.height / 2;
					sceneReal.camera.scroll.y = sceneReal.player.y - (playerScrollOffset - 50);
				}
			}
			else
			{
				reflectionHeightOffset = lowestReflectionHeightOffset;
				sceneReal.camera.scroll.y = 0;
			}
			sceneReal.matrix = new Matrix(1, 0, 0, 1, 0, -(FlxG.height / 2 - reflectionHeightOffset));
			sceneReflection.matrix = new Matrix(1, 0, 0, -1, 0, FlxG.height * 2 - (FlxG.height/2 - reflectionHeightOffset));
		}
	
		
		override public function draw():void 
		{
			sceneReal.draw();
			sceneReflection.draw();
			
			// Draw each scene with its matrix
			FlxG.camera.buffer.draw(sceneReal.camera.buffer, sceneReal.matrix, null, null, new Rectangle(0, 0, FlxG.width, FlxG.height / 2 + reflectionHeightOffset));
			//sceneReflection.camera.buffer.applyFilter(sceneReflection.camera.buffer, new Rectangle(0, 0, FlxG.width, FlxG.height), new Point(0, 0), new BlurFilter(4, 1, 1));
			FlxG.camera.buffer.draw(sceneReflection.camera.buffer, sceneReflection.matrix, new ColorTransform(0.7, 0.78, 0.9), null, new Rectangle(0, FlxG.height / 2 + reflectionHeightOffset, FlxG.width, FlxG.height / 2 - reflectionHeightOffset));
			// Draw the line between them.
			if (camerasLocked)
			{
				FlxG.camera.buffer.fillRect(new Rectangle(0, FlxG.height / 2 + reflectionHeightOffset, FlxG.width, 1), 0xff2255ff);
			}
			else
			{
				FlxG.camera.buffer.fillRect(new Rectangle(0, FlxG.height / 2 + reflectionHeightOffset - 1, FlxG.width, 3), 0xff000000);
				FlxG.camera.buffer.fillRect(new Rectangle(0, FlxG.height / 2 + reflectionHeightOffset, FlxG.width, 1), 0xffffffff);
			}
			
			// Draw wavey water.
			for (var i:int = FlxG.height / 2 + reflectionHeightOffset; i < FlxG.height; i++)
			{
				var off:Number = Math.sin(Math.cos(i / 4) + time * 3) * 0.05 + 0.9;
				FlxG.camera.buffer.copyPixels(FlxG.camera.buffer, new Rectangle(0, i, FlxG.width, 1), new Point(Math.sin(i * 1.5 + time * 1.5) * 1 + Math.cos(i * 0.5 + time * 7) * 1, i));
			}
			
			super.draw();
		}
		
	}

}